﻿using LightCAD.Core;
using LightCAD.MathLib;
using LightCAD.Runtime;
using LightCAD.Three;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Model
{
    //public class 
    public class ComponentInstance3dAction: IComponentAction
    {
        protected DocumentRuntime docRt;
        protected IDocumentEditor docEditor;
        protected CommandCenter commandCenter;
        protected ICommandControl commandCtrl;
        protected Model3DEditRuntime model3dRuntime;
        protected Snap3dRuntime snap3dRuntime;
        protected ComponentInstance3dAction() 
        {
        }
        protected ComponentInstance3dAction(IDocumentEditor docEditor)
        {
            this.SetDocEditor(docEditor);
        }
        public void SetDocEditor(IDocumentEditor docEditor) 
        {
            if (this.docEditor != docEditor)
            {
                this.docEditor = docEditor;
                this.docRt = docEditor.DocRt;
                this.commandCenter = this.docEditor.CommandCenter;
                this.commandCtrl = this.commandCenter.Commander;
                this.model3dRuntime = docEditor as Model3DEditRuntime;
                this.snap3dRuntime = this.model3dRuntime.Snap3DRuntime;
            }
        }
        public virtual List<Object3D> Render(IComponentInstance cptIns)
        {
            cptIns.ResetCache();
            var solids = cptIns.Solids;
            var result = new List<Object3D>();
            var insTrans = (cptIns as LcComponentInstance)?.Transform3d;
            foreach (var solid in solids)
            {
                solid.CreateMesh();
                var solidTrans = solid.Transform3d;
                var geoData = solid.Geometry;
                var geo = new BufferGeometry();
                geo.setAttribute("position", new BufferAttribute(geoData.Verteics, 3, false));
                geo.setIndex(new BufferAttribute(geoData.Indics, 1));
                geo.groups.AddRange(geoData.Groups);
                geo.ApplyTransform(solidTrans);
                geo.ApplyTransform(insTrans);
                geo.computeVertexNormals();
                geo.SetUV();
                var mats = cptIns.Definition.Solid3dProvider.AssignMaterialsFunc?.Invoke(cptIns,solid)??new LcMaterial[] { MaterialManager.DefaultMat};
                var mesh = new Mesh(geo, mats?.Select(m => RenderMaterialManager.GetRenderMaterial(m.Uuid)).ToArray());
                result.Add(mesh);
                mesh.name = solid.Name;

                if (solid.Edge != null)
                {
                    var lineGeoData = solid.Edge;
                    var lineGeo = new BufferGeometry();
                    lineGeo.setAttribute("position", new BufferAttribute(lineGeoData.Verteics, 3, false));
                    lineGeo.setIndex(new BufferAttribute(lineGeoData.Indics, 1));
                    lineGeo.ApplyTransform(solidTrans);
                    lineGeo.ApplyTransform(insTrans);
                    var line = new LineSegments(lineGeo, new LineBasicMaterial { color = new Color(0x00000000) });
                    result.Add(line);
                }
            }
            return result;

        }

        public void StartAction()
        {
            this.docEditor.CommandCenter.InAction = true;
        }
        public void EndAction()
        {
            this.commandCtrl.Prompt(string.Empty);

            this.commandCtrl.SetCurMethod(null);
            this.commandCtrl.SetCurStep(null);
            this.docEditor.CommandCenter.InAction = false;
        }
    }
}
